﻿using System;
using System.Collections.Generic;
using System.IO;
using ODM.Data.Model;

namespace ODM.Data.Common
{
    /// <summary>
    /// Represents ODM application data layer
    /// </summary>
    public abstract class DataSource
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DataSource"/> class.
        /// </summary>
        protected DataSource()
        {

        }

        /// <summary>
        /// Holds instnaces of initilized DataSource objects
        /// </summary>
        private static Dictionary<Type, DataSource> _instancesCache = new Dictionary<Type, DataSource>();

        /// <summary>
        /// Creates the specified data source type or gets an existing one if already exists
        /// </summary>
        /// <param name="dataSourceType">Type of the data source.</param>
        /// <returns></returns>
        public static DataSource Create(Type dataSourceType)
        {
            if (!_instancesCache.ContainsKey(dataSourceType))
            {
                DataSource dataSource = Activator.CreateInstance(dataSourceType) as DataSource;

                _instancesCache.Add(dataSourceType, dataSource);
            }

            return _instancesCache[dataSourceType];
        }

        #region DataValue operations

        /// <summary>
        /// Gets the data value.
        /// </summary>
        /// <param name="Id">The data value id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.DataValue GetDataValue(int dataValueId);

        /// <summary>
        /// Gets the data values.
        /// </summary>
        /// <param name="seriesId">The series id.</param>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.DataValue> GetDataValues(int seriesId);

        /// <summary>
        /// Gets the data values.
        /// </summary>
        /// <param name="seriesId">The series id.</param>
        /// <param name="startDate">The start date.</param>
        /// <param name="endDate">The end date.</param>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.DataValue> GetDataValues(int seriesId, DateTime startDate, DateTime endDate);

        /// <summary>
        /// Gets the data values.
        /// </summary>
        /// <param name="siteId">The site id.</param>
        /// <param name="variableId">The variable id.</param>
        /// <param name="qualityControlLevelId">The quality control level id.</param>
        /// <param name="methodId">The method id.</param>
        /// <param name="sourceId">The source id.</param>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.DataValue> GetDataValues(int siteId, int variableId, int qualityControlLevelId, int methodId, int sourceId);

        /// <summary>
        /// Creates the data value.
        /// </summary>
        /// <param name="dataValue">The data value.</param>
        /// <returns>Created data value; otherwise null.</returns>
        public abstract ODM.Data.Model.DataValue CreateDataValue(ODM.Data.Model.DataValue dataValue);

        /// <summary>
        /// Updates the data value.
        /// </summary>
        /// <param name="dataValue">The data value.</param>
        /// <returns>Updated data value; otherwise null.</returns>
        public abstract ODM.Data.Model.DataValue UpdateDataValue(ODM.Data.Model.DataValue dataValue);

        /// <summary>
        /// Deletes the data value.
        /// </summary>
        /// <param name="dataValue">The data value to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteDataValue(ODM.Data.Model.DataValue dataValue);

        #endregion

        #region Method operations

        /// <summary>
        /// Gets the method.
        /// </summary>
        /// <param name="Id">The method id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Method GetMethod(int methodId);

        /// <summary>
        /// Gets the method.
        /// </summary>
        /// <param name="description">Method  description.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Method GetMethod(string description);

        /// <summary>
        /// Gets the methods.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Method> GetMethods();

        /// <summary>
        /// Creates the method.
        /// </summary>
        /// <param name="description">Method description.</param>
        /// <returns>Created method; otherwise null.</returns>
        public virtual Method CreateMethod(string description)
        {
            return CreateMethod(new Method
            {
                Description = description,
            });
        }

        /// <summary>
        /// Creates the method.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>Created method; otherwise null.</returns>
        public abstract ODM.Data.Model.Method CreateMethod(ODM.Data.Model.Method method);

        /// <summary>
        /// Updates the method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <returns>Updated method; otherwise null.</returns>
        public abstract ODM.Data.Model.Method UpdateMethod(ODM.Data.Model.Method method);

        /// <summary>
        /// Deletes the method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteMethod(ODM.Data.Model.Method method);

        #endregion

        #region OffsetType operations

        /// <summary>
        /// Gets the type of the offset.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.OffsetType GetOffsetType(int Id);

        /// <summary>
        /// Gets the offset types.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.OffsetType> GetOffsetTypes();

        /// <summary>
        /// Creates the type of the offset.
        /// </summary>
        /// <param name="offsetType">Offset type to create.</param>
        /// <returns>Created offset type; otherwise null.</returns>
        public abstract ODM.Data.Model.OffsetType CreateOffsetType(ODM.Data.Model.OffsetType offsetType);

        /// <summary>
        /// Updates the type of the offset.
        /// </summary>
        /// <param name="offsetType">Offset type to update.</param>
        /// <returns>Updated offset type; otherwise null.</returns>
        public abstract ODM.Data.Model.OffsetType UpdateOffsetType(ODM.Data.Model.OffsetType offsetType);

        /// <summary>
        /// Deletes the type of the offset.
        /// </summary>
        /// <param name="offsetType">Offset type to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteOffsetType(ODM.Data.Model.OffsetType offsetType);

        #endregion

        #region Qualifier operations

        /// <summary>
        /// Gets the qualifier.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Qualifier GetQualifier(int Id);

        /// <summary>
        /// Gets the qualifier.
        /// </summary>
        /// <param name="code">Qualifier code.</param>
        /// <param name="description">Qualifier description.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Qualifier GetQualifier(string code, string description);

        /// <summary>
        /// Gets the qualifiers.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Qualifier> GetQualifiers();

        /// <summary>
        /// Creates the qualifier.
        /// </summary>
        /// <param name="code">Qualifier code.</param>
        /// <param name="description">Qualifier description.</param>
        /// <returns>Created qualifier; otherwise null.</returns>
        public virtual Qualifier CreateQualifier(string code, string description)
        {
            return CreateQualifier(new Qualifier
            {
                Code = code,
                Description = description,
            });
        }

        /// <summary>
        /// Creates the qualifier.
        /// </summary>
        /// <param name="qualifier">The qualifier.</param>
        /// <returns>Created qualifier; otherwise null.</returns>
        public abstract ODM.Data.Model.Qualifier CreateQualifier(ODM.Data.Model.Qualifier qualifier);

        /// <summary>
        /// Updates the qualifier.
        /// </summary>
        /// <param name="qualifier">The qualifier.</param>
        /// <returns>Updated qualifier; otherwise null.</returns>
        public abstract ODM.Data.Model.Qualifier UpdateQualifier(ODM.Data.Model.Qualifier qualifier);

        /// <summary>
        /// Deletes the qualifier.
        /// </summary>
        /// <param name="qualifier">The qualifier.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteQualifier(ODM.Data.Model.Qualifier qualifier);

        #endregion

        #region QualityControlLevel operations

        /// <summary>
        /// Gets the quality control level.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.QualityControlLevel GetQualityControlLevel(int Id);

        /// <summary>
        /// Gets the quality control level.
        /// </summary>
        /// <param name="code">The code.</param>
        /// <param name="definition">The definition.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.QualityControlLevel GetQualityControlLevel(string code, string definition);

        /// <summary>
        /// Gets the quality control levels.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.QualityControlLevel> GetQualityControlLevels();

        /// <summary>
        /// Creates the quality control level.
        /// </summary>
        /// <param name="qualityControlLevel">The quality control level.</param>
        /// <returns>Created quality control level; otherwise null.</returns>
        public abstract ODM.Data.Model.QualityControlLevel CreateQualityControlLevel(ODM.Data.Model.QualityControlLevel qualityControlLevel);

        /// <summary>
        /// Updates the quality control level.
        /// </summary>
        /// <param name="qualityControlLevel">The quality control level.</param>
        /// <returns>Updated quality control level; otherwise null.</returns>
        public abstract ODM.Data.Model.QualityControlLevel UpdateQualityControlLevel(ODM.Data.Model.QualityControlLevel qualityControlLevel);

        /// <summary>
        /// Deletes the quality control level.
        /// </summary>
        /// <param name="qualityControlLevel">The quality control level.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteQualityControlLevel(ODM.Data.Model.QualityControlLevel qualityControlLevel);

        #endregion

        #region Sample operations

        /// <summary>
        /// Gets the sample.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Sample GetSample(int Id);

        /// <summary>
        /// Gets the sample.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="code">The code.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Sample GetSample(string type, string code);

        /// <summary>
        /// Gets the samples.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Sample> GetSamples();

        /// <summary>
        /// Creates the sample.
        /// </summary>
        /// <param name="sample">Sample to create.</param>
        /// <returns>Created sample; otherwise null.</returns>
        public abstract ODM.Data.Model.Sample CreateSample(ODM.Data.Model.Sample sample);

        /// <summary>
        /// Updates the sample.
        /// </summary>
        /// <param name="sample">Sample to update.</param>
        /// <returns>Updated sample; otherwise null.</returns>
        public abstract ODM.Data.Model.Sample UpdateSample(ODM.Data.Model.Sample sample);

        /// <summary>
        /// Deletes the sample.
        /// </summary>
        /// <param name="sample">Sample to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteSample(ODM.Data.Model.Sample sample);

        #endregion

        #region SeriesCatalog operations

        /// <summary>
        /// Gets the series catalog.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.SeriesCatalog GetSeriesCatalog(int Id);

        /// <summary>
        /// Gets the series catalog.
        /// </summary>
        /// <param name="siteId">The site id.</param>
        /// <param name="variableId">The variable id.</param>
        /// <param name="methodId">The method id.</param>
        /// <param name="sourceId">The source id.</param>
        /// <param name="qualityControlLevelId">The quality control level id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.SeriesCatalog GetSeriesCatalog(int siteId, int variableId, int methodId, int sourceId, int qualityControlLevelId);

        /// <summary>
        /// Gets the series catalogs.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.SeriesCatalog> GetSeriesCatalogs();

        /// <summary>
        /// Gets the series catalog.
        /// </summary>
        /// <param name="siteCode">The site code.</param>
        /// <param name="siteName">Name of the site.</param>
        /// <param name="variableCode">The variable code.</param>
        /// <param name="variableName">Name of the variable.</param>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.SeriesCatalog> GetSeriesCatalog(string siteCode, string siteName, string variableCode, string variableName);

        /// <summary>
        /// Gets the series catalog.
        /// </summary>
        /// <param name="siteCodes">The site codes.</param>
        /// <param name="siteNames">The site names.</param>
        /// <param name="siteOperator">The site operator.</param>
        /// <param name="variableCodes">The variable codes.</param>
        /// <param name="variableNames">The variable names.</param>
        /// <param name="variableOperator">The variable operator.</param>
        /// <param name="methods">The methods.</param>
        /// <param name="sourceOrganizations">The source organizations.</param>
        /// <param name="sourceDescriptions">The source descriptions.</param>
        /// <param name="sourceOperator">The source operator.</param>
        /// <param name="generalCategories">The general categories.</param>
        /// <param name="valueTypes">The value types.</param>
        /// <param name="sampleMedium">The sample medium.</param>
        /// <param name="dataTypes">The data types.</param>
        /// <param name="qcLevels">The quality control levels.</param>
        /// <param name="beginDate">The begin date.</param>
        /// <param name="endDate">The end date.</param>
        /// <param name="observationCountOperator">The observation count operator.</param>
        /// <param name="observationCount">The observation count.</param>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.SeriesCatalog> GetSeriesCatalog(IEnumerable<string> siteCodes, IEnumerable<string> siteNames, QueryOperator siteOperator, IEnumerable<string> variableCodes, IEnumerable<string> variableNames, QueryOperator variableOperator, IEnumerable<string> methods, IEnumerable<string> sourceOrganizations, IEnumerable<string> sourceDescriptions, QueryOperator sourceOperator, IEnumerable<string> generalCategories, IEnumerable<string> valueTypes, IEnumerable<string> sampleMedium, IEnumerable<string> dataTypes, IEnumerable<int> qcLevels, DateTime? beginDate, DateTime? endDate, QueryOperator observationCountOperator, int? observationCount);

        /// <summary>
        /// Creates the series catalog.
        /// </summary>
        /// <param name="seriesCatalog">The series catalog to create.</param>
        /// <returns>Created series catalog; otherwise null.</returns>
        public abstract ODM.Data.Model.SeriesCatalog CreateSeriesCatalog(ODM.Data.Model.SeriesCatalog seriesCatalog);

        /// <summary>
        /// Updates the series catalog.
        /// </summary>
        /// <param name="seriesCatalog">The series catalog to update.</param>
        /// <returns>Updated series catalog; otherwise null.</returns>
        public abstract ODM.Data.Model.SeriesCatalog UpdateSeriesCatalog(ODM.Data.Model.SeriesCatalog seriesCatalog);

        /// <summary>
        /// Deletes the series catalog.
        /// </summary>
        /// <param name="seriesCatalog">The series catalog to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteSeriesCatalog(ODM.Data.Model.SeriesCatalog seriesCatalog);

        #endregion

        #region Site operations

        /// <summary>
        /// Gets the site.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Site GetSite(int Id);

        /// <summary>
        /// Gets the sites.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Site> GetSites();

        /// <summary>
        /// Creates the site.
        /// </summary>
        /// <param name="site">The site to create.</param>
        /// <returns>Created site; otherwise null.</returns>
        public abstract ODM.Data.Model.Site CreateSite(ODM.Data.Model.Site site);

        /// <summary>
        /// Updates the site.
        /// </summary>
        /// <param name="site">The site to update.</param>
        /// <returns>Updated site; otherwise null.</returns>
        public abstract ODM.Data.Model.Site UpdateSite(ODM.Data.Model.Site site);

        /// <summary>
        /// Deletes the site.
        /// </summary>
        /// <param name="site">The site to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteSite(ODM.Data.Model.Site site);

        #endregion

        #region Source operations

        /// <summary>
        /// Gets the source.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Source GetSource(int Id);

        /// <summary>
        /// Gets the sources.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Source> GetSources();

        /// <summary>
        /// Creates the source.
        /// </summary>
        /// <param name="source">The source to create.</param>
        /// <returns>Created source; otherwise null.</returns>
        public abstract ODM.Data.Model.Source CreateSource(ODM.Data.Model.Source source);

        /// <summary>
        /// Updates the source.
        /// </summary>
        /// <param name="source">The source to update.</param>
        /// <returns>Updated source; otherwise null.</returns>
        public abstract ODM.Data.Model.Source UpdateSource(ODM.Data.Model.Source source);

        /// <summary>
        /// Deletes the source.
        /// </summary>
        /// <param name="source">The source to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteSource(ODM.Data.Model.Source source);

        #endregion

        #region Unit operations

        /// <summary>
        /// Gets the unit.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Unit GetUnit(int Id);

        /// <summary>
        /// Gets the unit.
        /// </summary>
        /// <param name="unitName">Name of the unit.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Unit GetUnit(string unitName);

        /// <summary>
        /// Gets the units.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Unit> GetUnits();

        /// <summary>
        /// Creates the unit.
        /// </summary>
        /// <param name="unit">The unit to create.</param>
        /// <returns>Created unit; otherwise null.</returns>
        public abstract ODM.Data.Model.Unit CreateUnit(ODM.Data.Model.Unit unit);

        /// <summary>
        /// Updates the unit.
        /// </summary>
        /// <param name="unit">The unit to delete.</param>
        /// <returns>Updated unit; otherwise null.</returns>
        public abstract ODM.Data.Model.Unit UpdateUnit(ODM.Data.Model.Unit unit);

        /// <summary>
        /// Deletes the unit.
        /// </summary>
        /// <param name="unit">The unit to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteUnit(ODM.Data.Model.Unit unit);

        #endregion

        #region Variable operations

        /// <summary>
        /// Gets the variable.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Variable GetVariable(int Id);

        /// <summary>
        /// Gets the variable.
        /// </summary>
        /// <param name="variableCode">The variable code.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Variable GetVariable(string variableCode);

        /// <summary>
        /// Gets the variables.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Variable> GetVariables();

        /// <summary>
        /// Gets the variables.
        /// </summary>
        /// <param name="variableName">Name of the variable.</param>
        /// <param name="sampleMedium">The sample medium.</param>
        /// <param name="valueType">Type of the value.</param>
        /// <param name="timeSupport">The time support.</param>
        /// <param name="timeSupportUnitId">The time support unit id.</param>
        /// <param name="dataType">Type of the data.</param>
        /// <param name="generalCategory">The general category.</param>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Variable> GetVariables(string variableName, string sampleMedium, string valueType, double timeSupport, int timeSupportUnitId, string dataType, string generalCategory);

        /// <summary>
        /// Gets the variables for site.
        /// </summary>
        /// <param name="siteCode">The site code.</param>
        /// <param name="siteName">Name of the site.</param>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Variable> GetVariablesForSite(string siteCode, string siteName);

        /// <summary>
        /// Creates the variable.
        /// </summary>
        /// <param name="variable">The variable to create.</param>
        /// <returns>Created variable; otherwise null.</returns>
        public abstract ODM.Data.Model.Variable CreateVariable(ODM.Data.Model.Variable variable);

        /// <summary>
        /// Updates the variable.
        /// </summary>
        /// <param name="variable">The variable to update.</param>
        /// <returns>Updated variable; otherwise null.</returns>
        public abstract ODM.Data.Model.Variable UpdateVariable(ODM.Data.Model.Variable variable);

        /// <summary>
        /// Deletes the variable.
        /// </summary>
        /// <param name="variable">The variable to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteVariable(ODM.Data.Model.Variable variable);

        #endregion

        #region Term operations

        /// <summary>
        /// Gets the term.
        /// </summary>
        /// <param name="Id">The id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.Term GetTerm(int Id);

        /// <summary>
        /// Gets the terms.
        /// </summary>
        /// <param name="termType">Type of the term.</param>
        /// <returns></returns>
        public virtual IEnumerable<Term> GetTerms(TermType termType)
        {
            return GetTerms(termType, false);
        }

        /// <summary>
        /// Gets the terms.
        /// </summary>
        /// <param name="termType">Type of the term.</param>
        /// <param name="inUseOnly">if set to <c>true</c> the returns only terms that currently being used.</param>
        /// <returns></returns>
        public abstract IEnumerable<ODM.Data.Model.Term> GetTerms(TermType termType, bool inUseOnly);

        /// <summary>
        /// Creates the term.
        /// </summary>
        /// <param name="termType">Type of the term to create.</param>
        /// <param name="term">The term to create.</param>
        /// <returns>Created term; otherwise null.</returns>
        public abstract ODM.Data.Model.Term CreateTerm(TermType termType, ODM.Data.Model.Term term);

        /// <summary>
        /// Updates the term.
        /// </summary>
        /// <param name="termType">Type of the term to update.</param>
        /// <param name="term">The term to update.</param>
        /// <returns>Updated term; otherwise null.</returns>
        public abstract ODM.Data.Model.Term UpdateTerm(TermType termType, ODM.Data.Model.Term term);

        /// <summary>
        /// Deletes the term.
        /// </summary>
        /// <param name="termType">Type of the term to delete.</param>
        /// <param name="term">The term to delete.</param>
        /// <returns>true if deleted; otherwise false.</returns>
        public abstract bool DeleteTerm(TermType termType, ODM.Data.Model.Term term);

        #endregion

        #region Derive Data Series operations

        /// <summary>
        /// Creates the quality control level data series.
        /// </summary>
        /// <param name="seriesCatalogId">The series catalog id.</param>
        /// <param name="siteId">The site id.</param>
        /// <param name="variableId">The variable id.</param>
        /// <param name="methodId">The method id.</param>
        /// <param name="sourceId">The source id.</param>
        /// <param name="qualityControlLevelId">The quality control level id.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.SeriesCatalog CreateQualityControlLevelDataSeries(int seriesCatalogId, int siteId, int variableId, int methodId, int sourceId, int qualityControlLevelId);

        /// <summary>
        /// Creates the smoothed data series.
        /// </summary>
        /// <param name="seriesCatalogId">The series catalog id.</param>
        /// <param name="siteId">The site id.</param>
        /// <param name="variableId">The variable id.</param>
        /// <param name="methodId">The method id.</param>
        /// <param name="sourceId">The source id.</param>
        /// <param name="qualityControlLevelId">The quality control level id.</param>
        /// <param name="noDataValue">The no data value.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.SeriesCatalog CreateSmoothedDataSeries(int seriesCatalogId, int siteId, int variableId, int methodId, int sourceId, int qualityControlLevelId, double noDataValue);

        /// <summary>
        /// Creates the aggregate data series.
        /// </summary>
        /// <param name="seriesCatalogId">The series catalog id.</param>
        /// <param name="method">The method.</param>
        /// <param name="siteId">The site id.</param>
        /// <param name="variableId">The variable id.</param>
        /// <param name="methodId">The method id.</param>
        /// <param name="sourceId">The source id.</param>
        /// <param name="qualityControlLevelId">The quality control level id.</param>
        /// <param name="noDataValue">The no data value.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.SeriesCatalog CreateAggregateDataSeries(int seriesCatalogId, AggregateMethod method, int siteId, int variableId, int methodId, int sourceId, int qualityControlLevelId, double noDataValue);

        /// <summary>
        /// Creates the algebraic data series.
        /// </summary>
        /// <param name="seriesCatalogId">The series catalog id.</param>
        /// <param name="a">A.</param>
        /// <param name="b">The b.</param>
        /// <param name="c">The c.</param>
        /// <param name="d">The d.</param>
        /// <param name="e">The e.</param>
        /// <param name="f">The f.</param>
        /// <param name="siteId">The site id.</param>
        /// <param name="variableId">The variable id.</param>
        /// <param name="methodId">The method id.</param>
        /// <param name="sourceId">The source id.</param>
        /// <param name="qualityControlLevelId">The quality control level id.</param>
        /// <param name="noDataValue">The no data value.</param>
        /// <returns></returns>
        public abstract ODM.Data.Model.SeriesCatalog CreateAlgebraicDataSeries(int seriesCatalogId, double a, double b, double c, double d, double e, double f, int siteId, int variableId, int methodId, int sourceId, int qualityControlLevelId, double noDataValue);

        #endregion

        #region Export functions

        /// <summary>
        /// Exports the data values.
        /// </summary>
        /// <param name="seriesCatalogs">The series catalogs to export.</param>
        /// <param name="exportOptions">The export options.</param>
        /// <returns></returns>
        public abstract TextReader ExportDataValues(IEnumerable<ODM.Data.Model.SeriesCatalog> seriesCatalogs, ExportOptions exportOptions);

        /// <summary>
        /// Exports the metadata.
        /// </summary>
        /// <param name="seriesCatalogs">The series catalogs to export the metadata for.</param>
        /// <returns></returns>
        public abstract TextReader ExportMetadata(IEnumerable<ODM.Data.Model.SeriesCatalog> seriesCatalogs);

        #endregion

    }
}
